import { Observable } from 'rxjs'
import { HttpService } from '@nestjs/common'
import { Injectable } from '@nestjs/common'
import { RedisService } from './redis.service'
import { throwError, of } from 'rxjs'
import { map, switchMap } from 'rxjs/operators'

@Injectable()
export class WechatService {
  get accessToken(): Observable<string> {
    return this.refreshAccessToken()
  }
  get accessTokenUrl() {
    return `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${
      this.appid
    }&secret=${this.secret}`
  }

  get redisAccessTokenKey() {
    return this.appid + ':access_token'
  }

  public appid: string
  public secret: string
  /**
   * 微信账户
   * @param accountId 账户id
   * @param wechatId 微信id
   */
  constructor(public http: HttpService, public redis: RedisService) {}

  init(appid: string, secret: string) {
    this.appid = appid
    this.secret = secret
  }

  private refreshAccessToken(): Observable<string> {
    return this.redis.get(this.redisAccessTokenKey).pipe(
      switchMap(res => {
        if (res) {
          return of(res)
        } else {
          return this.http.get(this.accessTokenUrl).pipe(
            map(res => {
              return res.data
            }),
            switchMap((res: any) => {
              const errdesc = this.handlerErrorCode(res.errcode)
              if (res.errcode) {
                return throwError({
                  ...res,
                  errdesc
                })
              }
              const { access_token, expires_in } = res
              this.redis.set(this.redisAccessTokenKey, access_token, 'EX', expires_in)
              return of(access_token)
            })
          )
        }
      })
    )
  }

  handlerErrorCode(errcode: number) {
    switch (errcode) {
      case 0:
        return null
      case 40013:
        return 'appid无效'
      case -1:
        return '系统繁忙，此时请开发者稍候再试'
      case 40001:
        return '获取 access_token 时 AppSecret 错误，或者 access_token 无效。请开发者认真比对 AppSecret 的正确性，或查看是否正在为恰当的公众号调用接口'
      case 40002:
        return '不合法的凭证类型'
      case 40003:
        return '不合法的 OpenID ，请开发者确认 OpenID （该用户）是否已关注公众号，或是否是其他公众号的 OpenID'
      case 40004:
        return '不合法的媒体文件类型'
      case 40005:
        return '不合法的文件类型'
      case 40006:
        return '不合法的文件大小'
      case 40007:
        return '不合法的媒体文件 id'
      case 40008:
        return '不合法的消息类型'
      case 40009:
        return '不合法的图片文件大小'
      case 40010:
        return '不合法的语音文件大小'
      case 40011:
        return '不合法的视频文件大小'
      case 40012:
        return '不合法的缩略图文件大小'
      case 40013:
        return '不合法的 AppID ，请开发者检查 AppID 的正确性，避免异常字符，注意大小写'
      case 40014:
        return '不合法的 access_token ，请开发者认真比对 access_token 的有效性（如是否过期），或查看是否正在为恰当的公众号调用接口'
      case 40015:
        return '不合法的菜单类型'
      case 40016:
        return '不合法的按钮个数'
      case 40017:
        return '不合法的按钮个数'
      case 40018:
        return '不合法的按钮名字长度'
      case 40019:
        return '不合法的按钮 KEY 长度'
      case 40020:
        return '不合法的按钮 URL 长度'
      case 40021:
        return '不合法的菜单版本号'
      case 40022:
        return '不合法的子菜单级数'
      case 40023:
        return '不合法的子菜单按钮个数'
      case 40024:
        return '不合法的子菜单按钮类型'
      case 40025:
        return '不合法的子菜单按钮名字长度'
      case 40026:
        return '不合法的子菜单按钮 KEY 长度'
      case 40027:
        return '不合法的子菜单按钮 URL 长度'
      case 40028:
        return '不合法的自定义菜单使用用户'
      case 40029:
        return '不合法的 oauth_code'
      case 40030:
        return '不合法的 refresh_token'
      case 40031:
        return '不合法的 openid 列表'
      case 40032:
        return '不合法的 openid 列表长度'
      case 40033:
        return '不合法的请求字符，不能包含 \\uxxxx 格式的字符'
      case 40035:
        return '不合法的参数'
      case 40038:
        return '不合法的请求格式'
      case 40039:
        return '不合法的 URL 长度'
      case 40050:
        return '不合法的分组 id'
      case 40051:
        return '分组名字不合法'
      case 40060:
        return '删除单篇图文时，指定的 article_idx 不合法'
      case 40117:
        return '分组名字不合法'
      case 40118:
        return 'media_id 大小不合法'
      case 40119:
        return ''
      case 40121:
        return ''
      case 40132:
        return ''
      case 40137:
        return ''
      case 40155:
        return ''
      case 41001:
        return ''
      case 41002:
        return ''
      case 41003:
        return ''
      case 41004:
        return ''
      case 41005:
        return ''
      case 41006:
        return ''
      case 41007:
        return ''
      case 41008:
        return ''
      case 41009:
        return ''
      case 42001:
        return ''
      case 42002:
        return ''
      case 42003:
        return ''
      case 42007:
        return ''
      case 43001:
        return ''
      case 43002:
        return ''
      case 43003:
        return ''
      case 43004:
        return ''
      case 43005:
        return ''
      case 43019:
        return ''
      case 44001:
        return ''
      case 44002:
        return ''
      case 44003:
        return ''
      case 44004:
        return ''
      case 45001:
        return ''
      case 45002:
        return ''
      case 45003:
        return ''
      case 45004:
        return ''
      case 45005:
        return ''
      case 45006:
        return ''
      case 45007:
        return ''
      case 45008:
        return ''
      case 45009:
        return ''
      case 45010:
        return ''
      case 45011:
        return ''
      case 45015:
        return ''
      case 45016:
        return ''
      case 45017:
        return ''
      case 45018:
        return ''
      case 45047:
        return ''
      case 46001:
        return ''
      case 46002:
        return ''
      case 46003:
        return ''
      case 46004:
        return ''
      case 47001:
        return ''
      case 48001:
        return ''
      case 48002:
        return ''
      case 48004:
        return ''
      case 48005:
        return ''
      case 48006:
        return ''
      case 48008:
        return ''
      case 50001:
        return ''
      case 50002:
        return ''
      case 50005:
        return ''
      case 61451:
        return ''
      case 61452:
        return ''
      case 61453:
        return ''
      case 61454:
        return '调用接口的IP地址不在白名单中，请在接口IP白名单中进行设置。（小程序及小游戏调用不要求IP地址在白名单内。）'
      case 61455:
        return ''
      case 61456:
        return ''
      case 61457:
        return ''
      case 61450:
        return ''
      case 61500:
        return ''
      case 61501:
        return ''
      case 61502:
        return ''
      case 61503:
        return ''
      case 61504:
        return ''
      case 61505:
        return ''
      case 65306:
        return ''
      case 65307:
        return ''
      case 65308:
        return ''
      case 65309:
        return ''
      case 65310:
        return ''
      case 65311:
        return ''
      case 65312:
        return ''
      case 65313:
        return ''
      case 65314:
        return ''
      case 65316:
        return ''
      case 65317:
        return ''
      case 9001001:
        return 'POST 数据参数不合法'
      case 9001002:
        return '远端服务不可用'
      case 9001003:
        return 'Ticket 不合法'
      case 9001004:
        return '获取摇周边用户信息失败'
      case 9001005:
        return '获取商户信息失败'
      case 9001006:
        return '获取 OpenID 失败'
      case 9001007:
        return '上传文件缺失'
      case 9001008:
        return '上传素材的文件类型不合法'
      case 9001009:
        return '上传素材的文件尺寸不合法'
      case 9001010:
        return '上传失败'
      case 9001020:
        return '帐号不合法'
      case 9001021:
        return '已有设备激活率低于 50% ，不能新增设备'
      case 9001022:
        return '设备申请数不合法，必须为大于 0 的数字'
      case 9001023:
        return '已存在审核中的设备 ID 申请'
      case 9001024:
        return '一次查询设备 ID 数量不能超过 50'
      case 9001025:
        return '设备 ID 不合法'
      case 9001026:
        return '页面参数不合法'
      case 9001027:
        return '页面参数不合法'
      case 9001028:
        return '一次删除页面 ID 数量不能超过 10'
      case 9001029:
        return '页面已应用在设备中，请先解除应用关系再删除'
      case 9001030:
        return '一次查询页面 ID 数量不能超过 50'
      case 9001031:
        return '时间区间不合法'
      case 9001032:
        return '保存设备与页面的绑定关系参数错误'
      case 9001033:
        return '门店 ID 不合法'
      case 9001034:
        return '设备备注信息过长'
      case 9001035:
        return '设备申请参数不合法'
      case 9001036:
        return '查询起始值 begin 不合法'
    }
  }
}
